www.gusucode.com > VC++ 自制SQL数据库,含有服务端+客户端-源码程序 > VC++ 自制SQL数据库,含有服务端+客户端-源码程序/code/Server/ServerDoc.cpp

    //Download by http://www.NewXing.com
// ServerDoc.cpp : implementation file
//

#include "stdafx.h"
#include "miniSQL.h"
#include "ServerDoc.h"
#include "ServerView.h"

#include "ConnectDlg.h"
#include "User.h"
#include "table.h"
#include "SockExec.h"
#include "Error.h"
#include "AdrDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

extern CMiniSQLApp theApp;

/////////////////////////////////////////////////////////////////////////////
// CServerDoc

IMPLEMENT_DYNCREATE(CServerDoc, CDocument)

CServerDoc::CServerDoc()
{
	m_pSocket = NULL;
}

BOOL CServerDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	CConnectDlg dlg;
	if( dlg.DoModal() == IDOK )
	{
		m_pSocket = new CListeningSocket( this );
		if( m_pSocket->Create( dlg.m_port + 700, SOCK_STREAM, dlg.m_address ) )
		{
			if( m_pSocket->Listen() )
			{
				Message( "Successful creating ServeR!" );
				return TRUE;
			}
		}
		else
		{
			if( AfxMessageBox( "创建SOCKET失败,要重试吗?", MB_ICONQUESTION | MB_YESNO ) == IDYES )
				return OnNewDocument();
		}
	}

	::Message( "Error creating socket or user aborted!\n" );
	return FALSE;
}

CServerDoc::~CServerDoc()
{
	if( m_pSocket )
		delete m_pSocket;

	theApp.m_bConnection = FALSE;
}


BEGIN_MESSAGE_MAP(CServerDoc, CDocument)
	//{{AFX_MSG_MAP(CServerDoc)
	ON_COMMAND(ID_ADDRESS, OnAddress)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerDoc diagnostics

#ifdef _DEBUG
void CServerDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CServerDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CServerDoc serialization

void CServerDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CServerDoc commands

BOOL CServerDoc::OnSaveDocument(LPCTSTR lpszPathName) 
{
	return CDocument::OnSaveDocument( lpszPathName );
}

void CServerDoc::DeleteContents() 
{
	delete m_pSocket;
	m_pSocket = NULL;

	while( !m_connectionList.IsEmpty() )
	{
		CClientSocket* pSocket = ( CClientSocket* )m_connectionList.RemoveHead();
		CMsg msg( SERVER_CLOSE );
		msg.m_bClose = TRUE;

		SendMsg( pSocket, msg );

		if( !pSocket->IsAborted() )
		{
			pSocket->ShutDown();

			BYTE buffer[ 50 ];
			while( pSocket->Receive( buffer, 50 ) > 0 );
			delete pSocket;
		}
	}

	CDocument::DeleteContents();
}

BOOL CServerDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (!CDocument::OnOpenDocument(lpszPathName))
		return FALSE;

	return TRUE;
}

void CServerDoc::ProcessPendingAccept()
{
	CClientSocket* pSocket = new CClientSocket( this );

	if( m_pSocket->Accept( *pSocket ) )
	{
		pSocket->Init();
		m_connectionList.AddTail( pSocket );
	}
	else
		delete pSocket;
}

void CServerDoc::ProcessPendingRead(CClientSocket *pSocket)
{
	do
	{
		CMsg* pMsg = ReadMsg( pSocket );

		if( pMsg->m_bClose )
		{
			if( pSocket->m_name.GetLength() )
			{
				CString text( pMsg->m_msgList.GetHead() );
				CString address, strPort;
				UINT	port;
				pSocket->GetPeerName( address, port );
				strPort.Format( "%d", port );
				text += (CString)" (from " + address + ":" + strPort +
						  ") has disconnected from the server.";
				Message( text );
			}

			CloseSocket( pSocket );
			break;
		}

		switch( pMsg->m_cmdID )
		{
		case LOGON:
			{
				CString name, code;
				name = pMsg->m_msgList.RemoveHead();
				code = pMsg->m_msgList.RemoveHead();
				CMsg msg( LOGON );
				if( msg.m_nCount = (int)UserLogon( name, code ) )
				{
					pSocket->m_name = name;
					pSocket->m_type = (DWORD)msg.m_nCount;
					CString text = name;
					CString address, strPort;
					UINT	port;
					pSocket->GetPeerName( address, port );
					strPort.Format( "%d", port );
					text += (CString)" (from " + address + ":" + strPort +
							  ") has connected to the server.";
					Message( text );

					SendMsg( pSocket, msg );
					
					msg.Init();
					msg.m_cmdID = FILEBAR_INIT;
					PreScanFile( msg );
					SendMsg( pSocket, msg );
				}
				else
					SendMsg( pSocket, msg );
			}
			break;
		case FILEBAR_EXPAND:
			{
				CString tname = pMsg->m_msgList.GetHead();
				CMsg msg( FILEBAR_EXPAND );

				ScanFile( tname, msg );
				SendMsg( pSocket, msg );
			}
			break;
		case COMMAND:
			{
				CSockExec* pExec = new CSockExec( pMsg->m_msgList.GetHead(), pSocket, this );
				try
				{
					pExec->Exec();
				}
				catch( Error& e )
				{
					CString text( "ERRORS OCCOR, PROCESS ABORTED : \r\n\t" );
					text += e.GetErrStr();
					Message( text );

					CMsg msg( FAILED );
					msg.m_nCount = pExec->LineNo() - 1;
					msg.m_msgList.AddTail( e.GetErrStr() );
					CString str;
					str.Format( "%d", e.m_ErrType );
					msg.m_msgList.AddTail( str + "\n" );
					SendMsg( pSocket, msg );

					delete pExec;
				}
			}
			break;
		case STEP_COMMAND:
			{
				CSockExec* pExec = new CSockExec( pMsg->m_msgList.GetHead(), pSocket, this );
				try
				{
					pExec->SingleExec();
				}
				catch( Error& e )
				{
					CString text( "ERRORS OCCOR, PROCESS ABORTED : \r\n\t" );
					text += e.GetErrStr();
					Message( text );

					CMsg msg( FAILED );
					msg.m_nCount = pExec->LineNo() - 1;
					msg.m_msgList.AddTail( e.GetErrStr() );
					CString str;
					str.Format( "%d", e.m_ErrType );
					msg.m_msgList.AddTail( str );
					SendMsg( pSocket, msg );

					delete pExec;
				}
			}
			break;
		default:
			;
		}
	}
	while( !pSocket->m_pArchiveIn->IsBufferEmpty() );
}

CMsg* CServerDoc::ReadMsg(CClientSocket *pSocket)
{
	static CMsg msg;

	TRY
	{
		pSocket->ReceiveMsg( msg );
	}
	CATCH(CFileException, e)
	{
		Message( "Error reading socket!" );

		msg.m_bClose = TRUE;
		pSocket->Abort();
	}
	END_CATCH

	return &msg;
}

void CServerDoc::SendMsg(CClientSocket *pSocket, CMsg &msg)
{
	TRY
	{
		pSocket->SendMsg( msg );
	}
	CATCH( CFileException, e )
	{
		pSocket->Abort();

		Message( "Error sending message!" );
	}
	END_CATCH
}

void CServerDoc::Message(LPCTSTR lpszMessage)
{
	( (CServerView*)m_viewList.GetHead() )->Message( lpszMessage );
}

void CServerDoc::CloseSocket(CClientSocket *pSocket)
{
	pSocket->Close();

	POSITION pos, temp;
	for( pos = m_connectionList.GetHeadPosition(); pos; )
	{
		temp = pos;
		CClientSocket* pSock = ( CClientSocket* )m_connectionList.GetNext( pos );
		if( pSock == pSocket )
		{
			m_connectionList.RemoveAt( temp );
			break;
		}
	}

	delete pSocket;
}

DWORD CServerDoc::UserLogon(CString& name, CString& code)
{
	if( name == _T("admin") && code == _T("admin") )
		return LOG_ADMIN;
	else if( name == _T("superuser") && code == _T("superuser") )
		return LOG_SUPERUSER;
	else if( name == _T("user") && code == _T("user") )
		return LOG_USER;
	else 
	{
		CFileStatus status;
		CString path( theApp.dir );
		path += "\\user.dat";

		if( CFile::GetStatus( path, status ) )
		{
			CFile File( path, CFile::modeRead );
			CArchive ar( &File, CArchive::load );

			int length = 0;
				ar>>length;

			for( int i = 0; i < length; i++ )
			{
				CUser user;
				user.Serialize( ar );
				if( name == user.m_user && code == user.m_code )
					return user.m_type;
			}
			return 0;
		}
		else
		{
			CFile File( path, CFile::modeCreate | CFile::modeWrite );
			CArchive ar( &File, CArchive::store );
			int length = 0;
			ar<<length<<'\0';
			return 0;
		}
	}
}

void CServerDoc::PreScanFile( CMsg& msg )
{
	WIN32_FIND_DATA FileData; 
	HANDLE hFind;

	hFind = ::FindFirstFile( ".\\*.msl", &FileData);
	if( hFind != INVALID_HANDLE_VALUE ){
		CString fname = FileData.cFileName;
		int		len   = fname.GetLength();
		msg.m_msgList.AddTail( fname.Left( len - 4 ) );
		while( ::FindNextFile(hFind, &FileData) ){
			fname = FileData.cFileName;
			len   = fname.GetLength();
			msg.m_msgList.AddTail( fname.Left( len - 4 ) );
		}
	}
}

void CServerDoc::ScanFile( CString& tname, CMsg& msg )
{
	CTable table( (LPCTSTR) tname );
	msg.m_nCount = table.attr.attr.num;

	for( int i = 0; i < table.attr.attr.num; i++ )
	{
		CString str;
		str = table.attr.attr.attr[i].name;
		str += ":";
		switch( table.attr.attr.attr[i].type.id )
		{
		case _INT:		str += "int";	break;
		case _LONG:		str += "long";	break;
		case _FLOAT:	str += "float"; break;
		case _DATE:		str += "date";	break;
		case _STRING:	
			CString temp;
			temp.Format( "char[%d]", table.attr.attr.attr[i].type.size - 2 );
			str += temp;
			break;
		}

		msg.m_msgList.AddTail( str );
	}

	for( i = 0; i < table.attr.index_num; i++ )
	{
		CString str( _T("index:") );
		str += table.attr.index_table[i];
		
		msg.m_msgList.AddTail( str );
	}
}

void CServerDoc::ShowAddress()
{
	CAdrDlg dlg;

	CString address, strPort;
	UINT	port;
	m_pSocket->GetSockName( address, port );
	strPort.Format( "%d", port );

	address += " : " + strPort;

	dlg.m_address = address;
	dlg.DoModal();
}

void CServerDoc::OnAddress() 
{
	ShowAddress();
}